package com.thrid.party.codec.demo;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.time.format.DateTimeFormatter;
import java.util.Date;

public class ReportProcess {
    //private String identifier;

    private String msgType = "";
    private byte deviceReq = (byte) 0x00;
    private byte deviceRsp = (byte) 0x01;

    private String cmdCode = "";
    private byte normalReq = (byte) 0x01;
    private byte abnormalReq = (byte) 0x02;
    private byte repairReq = (byte) 0x03;
    private byte testReq = (byte) 0xFF;
    private byte selfOpenDegreeRsp = 0x05;
    private byte autoOpenDegreeRsp = 0x07;
    private byte setDeviceRsp = 0x09;
    private byte timeRsp = 0x0B;
    private byte temperatureRsp = 0x0D;

    private int errcode = 0;

    private int mid = 0;
    private int codeID = 0;

    private String modelNum = "";
    private long msgTime = 0;

    //serviceId=ValveBasic字段
    private int symbol1 = 0;
    private int basicGas = 0;
    private int symbol2 = 0;
    private int basicTemperature = 0;
    private String testData = "";

    //serviceId=Switch字段
    private int symbol3 = 0;
    private int openDegree = 0;

    //serviceId=Setting字段
    private int symbol4 = 0;
    private int frequency = 0;
    private int symbol5 = 0;
    private int alarm = 0;
    private int symbol6 = 0;
    private int calibration = 0;

    //serviceId=Time字段
    private long time = 0;

    //serviceId=Temperature字段
    private int symbol7 = 0;
    private int temperature = 0;

    private int version = 0;
    private int cs = 0;
    private byte endChar = 0x16;

    public ReportProcess(byte[] binaryData) {
        if (binaryData[1] == deviceReq) {
            msgType = "deviceReq";
            modelNum = Utilty.getInstance().bytes2HexStr(binaryData, 2, 16);
            msgTime = new Date((int) binaryData[18] + 100, (int) binaryData[19] - 1, (int) binaryData[20],
                    (int) binaryData[21], (int) binaryData[22], (int) binaryData[23]).getTime();
            if(binaryData[24] == normalReq) {
                cmdCode = "normalReq";
                symbol1 = binaryData[25];
                basicGas = Utilty.getInstance().bytes2Int(binaryData, 26, 2);
                symbol2 = binaryData[28];
                basicTemperature = Utilty.getInstance().bytes2Int(binaryData, 29, 2);
                version = binaryData[31];
                cs = binaryData[32];
                endChar = binaryData[33];
            } else if (binaryData[24] == abnormalReq) {
                cmdCode = "abnormalReq";
                symbol1 = binaryData[25];
                basicGas = Utilty.getInstance().bytes2Int(binaryData, 26, 2);
                symbol2 = binaryData[28];
                basicTemperature = Utilty.getInstance().bytes2Int(binaryData, 29, 2);
                version = binaryData[31];
                cs = binaryData[32];
                endChar = binaryData[33];
            } else if (binaryData[24] == repairReq) {
                cmdCode = "repairReq";
                symbol1 = binaryData[25];
                basicGas = Utilty.getInstance().bytes2Int(binaryData, 26, 2);
                symbol2 = binaryData[28];
                basicTemperature = Utilty.getInstance().bytes2Int(binaryData, 29, 2);
                version = binaryData[31];
                cs = binaryData[32];
                endChar = binaryData[33];
            } else if (binaryData[24] == testReq) {
                cmdCode = "testReq";
                testData = Utilty.getInstance().bytes2HexStr(binaryData, 0, binaryData.length);
                version = binaryData[25];
                cs = binaryData[26];
                endChar = binaryData[27];
            }


        }
        /*
        如果是设备对平台命令的应答，返回格式为：
       {
            "identifier":"123",
            "msgType":"deviceRsp",
            "errcode":0,
            "body" :{****} 特别注意该body体为一层json结构。
        }
	    */
        else if (binaryData[1] == deviceRsp) {
            msgType = "deviceRsp";
            modelNum = Utilty.getInstance().bytes2HexStr(binaryData, 2, 16);
            msgTime = new Date((int) binaryData[18] + 100, (int) binaryData[19] - 1, (int) binaryData[20],
                    (int) binaryData[21], (int) binaryData[22], (int) binaryData[23]).getTime();
            mid = Utilty.getInstance().bytes2Int(binaryData, 25, 2);
            codeID = Utilty.getInstance().bytes2Int(binaryData, 27, 3);
            errcode = binaryData[30];
            if (binaryData[24] == selfOpenDegreeRsp) {
                cmdCode = "selfOpenDegreeRsp";
                symbol3 = binaryData[31];
                openDegree = Utilty.getInstance().bytes2Int(binaryData, 32, 2);
                version = binaryData[34];
                cs = binaryData[35];
                endChar = binaryData[36];
            } else if (binaryData[24] == autoOpenDegreeRsp) {
                cmdCode = "autoOpenDegreeRsp";
                symbol3 = binaryData[31];
                openDegree = Utilty.getInstance().bytes2Int(binaryData, 32, 2);
                version = binaryData[34];
                cs = binaryData[35];
                endChar = binaryData[36];
            } else if (binaryData[24] == setDeviceRsp) {
                cmdCode = "setDeviceRsp";
                symbol4 = binaryData[31];
                frequency = Utilty.getInstance().bytes2Int(binaryData, 32, 2);
                symbol5 = binaryData[34];
                alarm = Utilty.getInstance().bytes2Int(binaryData, 35, 2);
                symbol6 = binaryData[37];
                calibration = Utilty.getInstance().bytes2Int(binaryData, 38, 2);
                version = binaryData[40];
                cs = binaryData[41];
                endChar = binaryData[42];
            } else if (binaryData[24] == timeRsp) {
                cmdCode = "timeRsp";
                time = new Date((int) binaryData[31] + 100, (int)binaryData[32] - 1, (int)binaryData[33], (int)binaryData[34],
                    (int)binaryData[35], (int)binaryData[36]).getTime();
                version = binaryData[37];
                cs = binaryData[38];
                endChar = binaryData[39];
            } else if (binaryData[24] == temperatureRsp) {
                cmdCode = "temperatureRsp";
                symbol7 = binaryData[31];
                temperature = Utilty.getInstance().bytes2Int(binaryData, 32, 2);
                version = binaryData[34];
                cs = binaryData[35];
                endChar = binaryData[36];
            }
        } else {
            return;
        }
    }

    public ObjectNode toJsonNode() {
        try {
            //组装body体
            ObjectMapper mapper = new ObjectMapper();
            ObjectNode root = mapper.createObjectNode();
            // root.put("identifier", this.identifier);
            root.put("msgType", this.msgType);
            //根据msgType字段组装消息体
            if (this.msgType.equals("deviceReq")) {
                ArrayNode arrynode = mapper.createArrayNode();
                if (cmdCode.equals("normalReq") || cmdCode.equals("abnormalReq") || cmdCode.equals("repairReq")) {
                    ObjectNode basicNode = mapper.createObjectNode();
                    basicNode.put("serviceId", "ValveBasic");
                    ObjectNode basicData = mapper.createObjectNode();
                    basicData.put("modelNum", modelNum);
                    basicData.put("msgTime", msgTime);
                    basicData.put("version", version);
                    basicData.put("cs", cs);
                    basicData.put("endChar", endChar);
                    basicData.put("cmdCode", cmdCode);
                    basicData.put("codeID", codeID);
                    basicData.put("gas", Utilty.caculateValue(this.symbol1, this.basicGas));
                    basicData.put("temperature", Utilty.caculateValue(this.symbol2, this.basicTemperature));
                    basicNode.put("serviceData", basicData);
                    arrynode.add(basicNode);
                } else if (cmdCode.equals("testReq")) {
                    ObjectNode basicNode = mapper.createObjectNode();
                    basicNode.put("serviceId", "ValveBasic");
                    ObjectNode basicData = mapper.createObjectNode();
                    basicData.put("testData", testData);
                    basicData.put("version", version);
                    basicData.put("cs", cs);
                    basicData.put("endChar", endChar);
                    basicNode.put("serviceData", basicData);
                    arrynode.add(basicNode);
                }
                root.put("data", arrynode);
            } else {
                root.put("errcode", this.errcode);
                root.put("mid", this.mid);//mid
                //组装body体，只能为ObjectNode对象
                ObjectNode body = mapper.createObjectNode();
                body.put("modelNum", modelNum);
                body.put("msgTime", msgTime);
                body.put("version", version);
                body.put("cs", cs);
                body.put("endChar", endChar);
                body.put("codeID", codeID);
                body.put("cmdCode", cmdCode);
                switch (cmdCode) {
                    case "selfOpenDegreeRsp":
                        body.put("serviceId", "Switch");
                        body.put("openDegreeResult", Utilty.caculateValue(this.symbol3, this.openDegree));
                        break;
                    case "autoOpenDegreeRsp":
                        body.put("serviceId", "Switch");
                        body.put("openDegreeResult", Utilty.caculateValue(this.symbol3, this.openDegree));
                        break;
                    case "setDeviceRsp":
                        body.put("serviceId", "Setting");
                        body.put("frequencyResult", Utilty.caculateValue(this.symbol4, this.frequency));
                        body.put("alarmResult", Utilty.caculateValue(this.symbol5, this.alarm));
                        body.put("calibrationResult", Utilty.caculateValue(this.symbol6, this.calibration));
                        break;
                    case "timeRsp":
                        body.put("serviceId", "Time");
                        body.put("timeResult", time);
                        break;
                    case "temperatureRsp":
                        body.put("serviceId", "Temperature");
                        body.put("temperatureResult", Utilty.caculateValue(this.symbol7, this.temperature));
                    break;
                }
                root.put("body", body);
            }
            return root;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}